/* ************************************************************************* **
**    OpenVFIFE - Open System for Vector Form Instrinsic                     **
**                Finite Element Method (VFIFE)                              **
**                GinkGo(Tan Biao)                                           **
**                                                                           **
**                                                                           **
** (C) Copyright 2021, The GinkGo(Tan Biao). All Rights Reserved.            **
**                                                                           **
** Commercial use of this program without express permission of              **
** GinkGo(Tan Biao), is strictly prohibited.  See                            **
** file 'COPYRIGHT'  in main directory for information on usage and          **
** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.                  **
**                                                                           **
** Developed by:                                                             **
**      Tan Biao (ginkgoltd@outlook.com)                                     **
**                                                                           **
** ************************************************************************* */

// $Date: 2020-05-22 $
// Written: Tan Biao
// Revised:
//
// Purpose: This file contains the class definition for Particle

// The interface:
//

#ifndef INTEGRATOR_H_
#define INTEGRATOR_H_
#include <iostream>
#include <vector>
#include <cmath>
#include "Eigen/Dense"


class BaseIntegrator
{
    /*
    Atrributes:
        * nodes_ - number of integral nodes
        * x_ - coordinates of integral nodes
        * w_ - the corresponding weights

    Methods:
        integrate1d(const vector<double> &val, double x1, double x2)
        * single integrals
        * val - function values at integral nodes, [f(x1), f(x2), ... f(xn)],
        *       val.size() == nodes
        * x1, x2 - lower and upper limit of the integral

        integrate2d(const vector<vectro<double>> &val, double x1, double x2,
                    double y1, double y2)
        * double integrals
        * val - fuction values at integral nodes, [[f(x1, y1), f(x2, y1),...],
        *                                          [f(x1, y2), f(x2, y2),...],
        *                                          ...
        *                                          [f(x1, yn), f(x2, yn),...]]

        integrate3d(const vector<vector<vector<double>>> &val, double x1,
                    double x2, double y1, double y2, double z1, double z2)
        * triple integrals

    */
    protected:
        int nodes_;
        std::vector<double> x_;
        std::vector<double> w_;

    public:
        BaseIntegrator(int nodes);
        virtual ~BaseIntegrator();
        double x(int i) const;
        double w(int i) const;
        // single integrals
        double integrate1d(const std::vector<double> &val,
                           double x1, double x2) const;
        double integrate1d(const std::vector<double*> &val,
                           double x1, double x2) const;

        // double integrals
        double integrate2d(const std::vector<std::vector<double>> &val,
                           double x1, double x2, double y1, double y2) const;
        double integrate2d(const std::vector<std::vector<double*>> &val,
                           double x1, double x2, double y1, double y2) const;

        // triple integrals
        double integrate3d(const std::vector<std::vector<std::vector<double>>>
                           &val, double x1, double x2, double y1, double y2,
                           double z1, double z2) const;
        double integrate3d(const std::vector<std::vector<std::vector<double*>>>
                           &val, double x1, double x2, double y1, double y2,
                           double z1, double z2) const;
};


class GaussLegendre:public BaseIntegrator
{
    /* A simple version of Gauss-Legendre integration, which support 1~10
    * integartion points at most.
    */
    public:
        GaussLegendre(int nodes);
        virtual ~GaussLegendre();
};


class GaussLobatto:public BaseIntegrator
{
    /* A simple version of Gauss-Lobatto integration, which support 2~10
    * integartion points at most.
    */
    public:
        GaussLobatto(int nodes);
        virtual ~GaussLobatto();
};

#endif